package com.feri.fc.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.feri.fc.admin.param.PageParam;
import com.feri.fc.admin.param.ServeAdd;
import com.feri.fc.admin.service.ServeService;
import com.feri.fc.config.RedisKeyConfig;
import com.feri.fc.config.RocketMQConfig;
import com.feri.fc.dao.ServeDao;
import com.feri.fc.entity.Hospital;
import com.feri.fc.entity.Serve;
import com.feri.fc.vo.PageData;
import com.feri.fc.vo.R;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 千锋Java,为你而生！
 *
 * @Author: Feri
 * @Date:2024/11/27 11:34
 * @Modified:
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class ServeServiceImpl implements ServeService {
    private final ServeDao dao;
    @Resource
    private RedisTemplate<Object,Object> redisTemplate;
    private final RocketMQTemplate rocketMQTemplate;

    @Transactional
    @Override
    public R add(ServeAdd add) {
        //1.名称唯一性
        LambdaQueryWrapper<Serve> wrapper=new LambdaQueryWrapper<>();
        wrapper.eq(Serve::getTitle,add.getTitle());
        Serve serve=dao.selectOne(wrapper);
        if(serve!=null){
            return R.fail("亲，名称已存在！");
        }
        //2.新增
        serve=new Serve();
        BeanUtils.copyProperties(add,serve);
        serve.setStatus("有效");
        serve.setCreateTime(new Date());
        serve.setUpdateTime(new Date());
        dao.insert(serve);
        log.info("新增服务={}",serve.getId());
        //3.缓存 为什么缓存？高频访问，低频修改
        //缓存--Redis
        //Redis使用考虑5个问题？
        //1.为什么使用Redis? 快-原因：1.内存 2.协议 resp 3.底层结构 4.多路复用
        //2.使用哪种数据类型？解释原因 8种 Hash 便于通过医院查询
        //3.要不要设置有效期？解释 不需要设置 永久有效
        //4.存储什么样的数据？说清楚 key: fc:caregiver:serves   field: 医院ID value:服务产品对象
        //5.数据同步实现？缓存需要（数据同时存储在多个地方）,要
        //考虑Redis常见面试题？1.sds ziplist skiplist  2.失效策略 3.淘汰机制 4.穿透 5.击穿 6.雪崩 7.倾斜 8.集群策略
        //验证是否存在对应医院 陪诊服务信息数据
        List<Serve> list;
        if(redisTemplate.hasKey(RedisKeyConfig.HOSPITAL_SERVES) && redisTemplate.opsForHash().hasKey(RedisKeyConfig.HOSPITAL_SERVES,serve.getHospitalId())){
            //存在 取出来，添加到对应集合中
            list=(List)redisTemplate.opsForHash().get(RedisKeyConfig.HOSPITAL_SERVES,serve.getHospitalId());
        }else {
            list=new ArrayList<>();
        }

        list.add(serve);
        System.err.println(list);
        redisTemplate.opsForHash().put(RedisKeyConfig.HOSPITAL_SERVES,serve.getHospitalId(),list);

        return R.ok();
    }

    @Override
    public R update(Serve serve) {
        //直接修改Redis
        serve.setUpdateTime(new Date());

        List list=(List) redisTemplate.opsForHash().get(RedisKeyConfig.HOSPITAL_SERVES,serve.getHospitalId());
        for (int i = 0; i <list.size() ; i++) {
            Serve s= (Serve) list.get(i);
            if(s.getId()==serve.getId()){
                list.add(i,serve);
                break;
            }
        }
        //更新Redis
        redisTemplate.opsForHash().put(RedisKeyConfig.HOSPITAL_SERVES,serve.getHospitalId(),list);

        //发送MQ 实现 基于MQ的异步消息通信 达到陪诊服务信息的数据同步 更新Redis-->发送MQ-->监听-->更新Mysql
        rocketMQTemplate.convertAndSend(RocketMQConfig.TOPIC_SERVES,serve);

        return R.ok();
    }

    @Override
    public PageData<Serve> queryPage(PageParam param) {
        //原来这么写，现在 需要走Redis
//        LambdaQueryWrapper<Serve> wrapper=new LambdaQueryWrapper<>();
//        wrapper.orderByDesc(Serve::getCreateTime);
//        Page<Serve> page=dao.selectPage(new Page<>(param.getPage(),param.getLimit()),wrapper);
//        return PageData.ok(page.getTotal(),page.getPages(),page.getRecords());

        Map map=redisTemplate.opsForHash().entries(RedisKeyConfig.HOSPITAL_SERVES);
        List list=new ArrayList();

        for (Object key:map.keySet()) {
            List serves=(List) map.get(key);
            list.addAll(serves);
        }
        if(list!=null && list.size()>0) {
            //根据分页 计算起始索引
            int index = (param.getPage() - 1) * param.getLimit();
            //计算总页数
            long pages = list.size() % param.getLimit() == 0 ? list.size() / param.getLimit() : list.size() / param.getLimit() + 1;
            int end=index+param.getLimit();
            if(end>list.size()){
                end=list.size();
            }
            // [起始索引，结束索引 )
            return PageData.ok((long) list.size(), pages, list.subList(index, end));
        }else {
            return PageData.ok(0L,0L,null);
        }
    }
}
